package com.singleton;

//
// Danger!  This implementation of Singleton not
// guaranteed to work prior to Java 5
//

/**
 * 线程安全的，并且只有第一次初始化的时候是线程安全的，之后就不需要了
 * 
 * @author dell
 * 
 */
public class Singleton2 {
	//不加volatile关键字：存在的问题是无序性。 
	//new Singleton2()操作是无序的，它可能会被编译成： 
	//- a. 先分配内存，让instance指向这块内存 
	//- b. 在内存中创建对象
	//然而我们需要意识到这么一个问题，synchronized虽然是互斥的，但不代表一次就把整个过程执行完，它在中间是可能释放时间片的，时间片不是锁。（我因为这里没转过来，耽误了很多时间） 
	//也就是说可能在a执行完后，时间片被释放，线程2执行到1，这时他读到的instance是不是null呢？（标记1） 
	//基于可见性，可能是null，也可能不是null。 
	//非常奇葩的是，在这个例子中，如果读到的是null，反而没问题了，接下来会等待锁，然后再次判断时不为null，最后返回单例。 
	//如果读到的不是null，那么坏了，按逻辑它就直接return instance了，这个instance还没执行构造参数，去做事情的话，很可能就崩溃了。
	
	//加了volatile关键字，那么会有什么现象？ 
	//从1.5开始，加了volatile关键字的引用，它的初始化就不能是： 
	//- a. 先分配内存，让instance指向这块内存 
	//- b. 在内存中创建对象
	//而应该是： 
	//- a.在内存中创建对象 
	//- b.让instance指向这个对象.
	private volatile static Singleton2 uniqueInstance;

	private Singleton2() {
	}

	public static Singleton2 getInstance() {
		if (uniqueInstance == null) {
			synchronized (Singleton2.class) {
				if (uniqueInstance == null) {
					uniqueInstance = new Singleton2();
				}
			}
		}
		return uniqueInstance;
	}
}
